#lang racket
(require "note.rkt")
(require "images.rkt")
(require rsound)
(provide monde%)

;variables globales
(define TICKS-PAR-SECONDE 48)

;monde.rkt
;version 1.0.0
(define monde%
  (class object%
    ;----------------------------------- Attributs ----------------------------;
    (init-field (partition '()))
    (init-field (temps-attente TICKS-PAR-SECONDE))
    (init-field (images '()))
    (init-field (animations'()))
    (init-field (ps (make-pstream)))
    (init-field (fini? #f))
    
    ;----------------------------------- Methodes -----------------------------;
    ;partition-vide?
    ;retourne #t si la partition est vide
    (define/public (partition-vide?)
      (null? partition))
    
    ;afficher
    ;affiche une description du monde dans la console
    (define/public (afficher)
      (printf "monde : ~a \n ~a" partition temps-attente))
    
    ;lire-partition
    ;lit le contenu de la partition au temps courant, et modifie le monde
    ;en conséquence.
    (define/public (lire-partition)
      (cond ((and (= temps-attente 0) (partition-vide?)) (fermer-animation))
            ((= temps-attente 0) (lire-note))
            (else (set! temps-attente (- temps-attente 1)))
            ))
    
    ;lire-note
    ;lit la première note de la partition
    (define/public (lire-note)
      (define note-courante (car partition))
      (define images-eligibles   ;On définit la liste des images qui attendent d'être animées et qui sont du bon type
        (filter (λ (img) (and
                          (not (send img get-is-animated))
                          (equal? (send img get-type) (send note-courante get-image-type))))       ;COMMENT MARCHE GETCLASS ???? et eval ?
                images))
      (if (not (null? images-eligibles))         ;SI la liste d'images disponibles n'est pas vide, on lie l'animation désirée
          (begin                                 ;à une image tirée au hasard dans cette liste.
            (bind-animation-to-image
             (list-ref (random (length images-eligibles)) images-eligibles)
             (send note-courante get-animation-type))
            (pstream-play ps (send note-courante get-son)) ;puis on joue le son et les animations
            (jouer-animations))
          (begin                                  ;SINON on ne fait que jouer le son et les animations
            (pstream-play ps (send note-courante get-son))
            (jouer-animations))))
    
    ;jouer-animations
    ;joue la liste des animations
    (define/public (jouer-animations)
      (for ([animation-courante (in-list animations)])
        (send animation-courante jouer)))
    
    ;bind-animation-to-image
    ;Lie une nouvelle animation à une image existante en fonction d'une animation-type puis ajoute l'animation
    ;à la liste des animations présentes dans le monde
    (define/public (bind-animation-to-image img anim-type)
      (define nouvelle-animation (eval `(new ,anim-type (image-cible ,img)))) ;premier candidat pour le champ "animation-type" : 'animation%
      (set! animations (cons nouvelle-animation animations))
      img)
    
    ;fermer-animation
    ;méthode privée chargée de déclencher le processus de fin du monde
    (define/private (fermer-animation)
      (set! fini? #t))
    
    (super-new)))
;TESTS
;(define ntest (new note%))
;(define ptest (list ntest ntest))
;(define img-test (new image%))
;(define mtest (new monde% (partition ptest)
;                   (images (list img-test (new image% (is-animated #f))))))